import { glDefine } from "../../Config/GLDefine";

//import { cc.vv.baseDispatch } from "./BaseDispatch";
export default class BaseWebSocket {
	_host = "";
	_port = "";
	_ws_client = null;
	_sequenceMsg = null; //msg in sequence sending;
	_is_opened = false;
	_connecting = false;

	_proto_filter = null;
	//_re_connect_num= 0; //断线重连次数;

	_need_close = false;

	_is_open_heart_beat = false; //heart switch;
	_pre_heart_receive_time = -1; //上一个心跳到达时间;
	_heart_return_time = 0; //心跳回来时间
	_heart_beat_handler = null; //心跳句柄;
	_heart_beat_time_interval = 5000; // 心跳间隔时间, 10秒进行一次重连;
	_connect_time_out = 3000; // 创建连接超时时间

	_close_reconnect_handler = null;

	_loseHeartNum = 0;

	_ishowtips = false;

	readyState = {
		OPEN: 1, // 网络已建立
		CLOSED: 2, // 网络异常断开
		WAITING: 3, // 网络状态不良，等待连接中，需要展示菊花
		CONNECTING: 4 // 网络状态恢复正常，需要关闭菊花
	};

	//constructor() {}

	init(host, port) {
		cc.log("baseWebSocket init", cc.vv.NetGameHall);

		var self = this;

		this._host = host || this._host;
		this._port = port || this._port;

		this._sequenceMsg = {};
		this._proto_filter = cc.vv.proto_filter;
		this._proto_filter.init(function (succ) {
			if (succ) {
				self.connect();
			}
		});

	}
	connect() {
		// this._is_opened = false;
		//cc.vv.GLDefine.IsOpen = false;
		console.log("WebSocket____ip1 = " + this._host);
		console.log("WebSocket____port1 = " + this._port);
		var cfg = cc.vv.GLSDKMgr.getServerIpAndPort(this._host, this._port);
		if (!cfg) {
			return;
		}
		console.log("WebSocket____gamhallNetwork = " + JSON.stringify(cfg));
		var tar_ip = cfg.ip;
		var tar_port = cfg.port;
		var url = "ws://" + tar_ip + ":" + tar_port + "/";
		console.log("WebSocket   Trying to connect to server : " + url);

		//   this._connecting = true;

		this._ws_client = new WebSocket(url);
		this._ws_client.onopen = this.onOpen.bind(this);
		this._ws_client.onmessage = this.onMessage.bind(this);
		this._ws_client.onerror = this.onError.bind(this);
		this._ws_client.onclose = this.onClose2.bind(this);
		this._ws_client.binaryType = "arraybuffer";
	}
	stopHeartBeat() {
		console.log("WebSocket_______stopHeartBeat");
		this._is_open_heart_beat = false;
		if (this._heart_beat_handler) {
			clearInterval(this._heart_beat_handler);
			this._heart_beat_handler = null;
		}
	}
	openHeartBeat() {
		console.log("WebSocket_______openHeartBeat");
		this._is_open_heart_beat = true;
	}
	onOpen() {
		// if (this.callBack) {
		//   this.callBack(true);
		// }
		//   this._is_opened = true;
		//cc.vv.GLDefine.IsOpen = true;

		//  this._connecting = false;
		//cc.vv.GLDefine.IsReconnecting = false;

		this._pre_heart_receive_time = -1;
		this._heart_return_time = 0;
		console.log(
			"WebSocket    success to connect to " + this._host + ":" + this._port
		);

		if (cc.vv.baseDispatch) {
			cc.vv.baseDispatch.clear();
		}
		this.runHeartBeat();

		cc.vv.GLConfig.isConnected = true;

		console.log("-------------checkConnect, to close page_reconnect   33!");
		cc.vv.UIMgr.close(cc.vv.GLConfig.reconnect_path, cc.vv.UIMgr.closeType.destory);
		cc.vv.eventCustom.emit("openSocket");//单独发给聊天列表界面
		if (this._close_reconnect_handler) {
			clearTimeout(this._close_reconnect_handler);
		}
		// if (this._error_reconnect_handler) {
		//     clearTimeout(this._error_reconnect_handler);
		// }
	}

	/**
	 * 心跳启动逻辑;
	 */
	runHeartBeat() {
		console.log("开启心跳");
		this._loseHeartNum = 0;
		this.stopHeartBeat();
		var self = this;
		this._heart_beat_handler = setInterval(function () {
			if (self._is_open_heart_beat) {
				self.sendHeart();
			}
		}, this._heart_beat_time_interval);

		if (this._is_open_heart_beat) {
			//console.log("-------send heart first do!!!!!!!!!!!!!");
			this.sendHeart();
		}
		cc.vv.GLConfig.re_connect_num = 0;
		// this._re_connect_num = 0;
	}
	send(msgName, msgData, callback) {
		msgData.cmd = msgName;
		if (cc.vv.baseDispatch.isCallBackRegister(msgName)) {
			return;
		}
		console.log(
			"\n--客户端->服务器-----------------Message_CTS-------------" +
			msgName +
			"----------------------\n",
			msgData,
			JSON.stringify(new Date()),
			"\n"
		);

		cc.vv.baseDispatch.registerCallBack(msgName, callback);
		this._send(msgData);
	}
	_send(msgData) {
		if (this._ws_client && this._ws_client.readyState === WebSocket.OPEN) {
			if (msgData.cmd != "Heart") {
				cc.log(msgData);
			}

			var msg = this._proto_filter.encode(msgData);
			this._ws_client.send(msg);
		} else {
			//cache failed msg;
			// if(msgData && msgData.cmd){
			//     this._cacheMsg.push(msgData);
			// }
		}
	}

	/**
	 * 请求心跳;
	 */
	sendHeart() {
		//console.log("______send Heart_____");
		var dt = this._heart_return_time - this._pre_heart_receive_time;
		if (dt < 0) {
			console.log("WebSocket   endHeart DT < 0", dt, this._loseHeartNum);
			//上次心跳没收到回复
			//如果是打开了的 如果是连接着的
			if (this._ws_client && this._ws_client.readyState === WebSocket.OPEN) {
				console.log("WebSocket sendHeart+++++++++");
				if (!this._loseHeartNum) this._loseHeartNum = 0;
				this._loseHeartNum++;
				//第二次心跳没收到
				if (this._loseHeartNum >= 1) {
					this._loseHeartNum = 0;
					//cc.vv.UIMgr.open(cc.vv.GLConfig.reconnect_path);
					cc.vv.GLUtils.showTips('网络连接异常,请检查网络!');
					this.close();
					this.reConnect();
					return;
				}
			}
		} else {
			this._loseHeartNum = 0;
		}

		var msg = {
			cmd: "Heart"
		};
		cc.vv.GLNetDataModel.setSendTime();

		//设置当前时间
		this._pre_heart_receive_time = cc.vv.GLUtils.getLocalTime();
		this._send(msg);
	}
	/**
	 * 获得心跳;
	 */
	receiveHeart(data) {
		// console.log("_____receiveHeart____");
		cc.vv.GLConfig.isConnected = true;
		//设置回复时间
		this._heart_return_time = cc.vv.GLUtils.getLocalTime();
		cc.vv.GLNetDataModel.setReceiveTime();
		cc.vv.GLNetDataModel.setDiffServerTime(data.servertime * 1000);
	}

	reConnect() {
		console.log("WebSocket  -------reConnect,cc.vv.sceneName   is ",cc.vv.sceneName);
		this._ws_client = null;
	}
	/**
	 * 错误处理;
	 */
	onError(e) {
		console.log("WebSocket   -------------onError:" + JSON.stringify(e));
	}
	/**
	 * 主动关闭;
	 */
	close() {
		console.log("WebSocket close   111111111111111111111111111111111111111");
		if (this._ws_client && this._ws_client.readyState === WebSocket.OPEN) {
			console.log(" WebSocket   active to close socket inner!!!!!");
			this.stopHeartBeat();
			if (this._close_reconnect_handler) {
				clearTimeout(this._close_reconnect_handler);
			}

			cc.vv.GLConfig.isConnected = false;
			this._ws_client.close();

			this._ws_client = null;
		}
	}
	onClose2(e) {
		console.log("WebSocket   -------------onClose2:" + JSON.stringify(e), e.code);
		cc.vv.UIMgr.close(cc.vv.GLConfig.waiting_path, cc.vv.UIMgr.closeType.hide);

		if (!this._ws_client) {
			console.log("WebSocket   onClose2++++++++++++++++++++++");
			return;
		}
		//4001：被顶掉 4002：账号异常（封号、密码错误、token失效） 4003:关服
		if (e.code === 4001 || e.code === 4002 || e.code === 4003) {
			this.stopHeartBeat();
			if (this._close_reconnect_handler) {
				clearTimeout(this._close_reconnect_handler);
			}

			cc.vv.GLConfig.isConnected = false;
			this._ws_client.close();

			this._ws_client = null;
			var str = "";
			if (e.code === 4001) {
				str = "系统检测到您的账户正在其他地方登录，您即将返回登录界面！";
			} else if (e.code === 4002) {
				str = e.reason;//"您的账号已经被封";
			} else if (e.code === 4003) {
				str = "服务器已关闭，请退出到登录界面！";
			}

			cc.vv.GLUtils.showAlert1(str, function () {
				//cc.vv.GLUtils.clearUserInfo();

				if (cc.vv.Login) {
					if (cc.vv.NetGameHall) {
						cc.vv.NetGameHall.close(true);
						cc.vv.NetGameHall = null;
					}
					cc.vv.GLUtils.clearAccountInfo();
					cc.vv.Login.relogin();
				} else {
					cc.vv.GLUtils.changeAccount();
				}
			});
			return;
		}

		this._ws_client = null;
		console.log("WebSocket   onClose-------------------------");

		this._sequenceMsg = {};

		if (cc.vv.baseDispatch) {
			cc.vv.baseDispatch.clear();
		}
		this.stopHeartBeat();
		var self = this;

		cc.vv.GLConfig.isConnected = false;

		if (this._close_reconnect_handler) {
			clearTimeout(this._close_reconnect_handler);
		}

		//如果不是需要断开
		// if (!this._need_close) {

		//打开重连界面
		//本地缓存的大厅的ip
		if (cc.vv.Login) {
			cc.vv.GLUtils.showTips('网络不稳定,请检查网络!');
			cc.vv.GLUtils.clearAccountInfo();
			cc.vv.Login.relogin();
			return
		}

		// cc.vv.UIMgr.open(cc.vv.GLConfig.reconnect_path);
		cc.vv.GLUtils.showTips('网络连接异常,请检查网络!');
		console.log(
			"WebSocket   reconnect-------------------------",
			cc.vv.GLConfig.re_connect_num
		);


		//2s后
		this._close_reconnect_handler = setTimeout(function () {
			// if (!self._need_close) {
			//如果没有显示Tips   并且重连次数大于4次
			if (!self._ishowtips && cc.vv.GLConfig.re_connect_num > 2) {
				//弹窗提示;
				self._ishowtips = true;
				//var str = cc.vv.GLocalizationDataModel.getStringByKey("tips_reconnect_long")
				var str = "重连失败，请检查网络";
				var fun_ok = function () {
					self._ishowtips = false;

					cc.vv.GLConfig.re_connect_num = 0;
					self.reConnect();
					// self.init(self._host, self._port);
				};
				var fun_cancel = function () {
					self._ishowtips = false;
					//cc.vv.GLDefine.IsReconnectFail = false;

					cc.vv.GLUtils.restart();
				};
				cc.vv.GLUtils.showAlert1(str, fun_ok, fun_cancel, cc.vv.persistNode, "", "重新连接", "返回登录");//, '', '重新连接', '等待'
				return;
			}
			console.log("WebSocket   -----------------onClose timeout");
			++cc.vv.GLConfig.re_connect_num;
			self.reConnect();
			//self.init(self._host, self._port);
			// }
		}, 2000);
		return true;
		//  }
	}

	onMessage(e) {
		if (this._ws_client && this._ws_client.readyState == WebSocket.OPEN) {
			this._proto_filter.decode(e.data, this._onMessage.bind(this));
			//return;
		}
		//服务器下发消息接口 Mark:
		//cc.log("++++++++++++++++++++++++++++ e",e);
		// this._proto_filter.decode(e.data, this._onMessage.bind(this));
		//cc.log("++++++++++++++++++++++++++++ e",e);
	}
	_onMessage(data) {
		if (!data) {
			//异常消息
			console.log("//异常消息 data is null!");
			return;
		}
		var cmd = data.cmd;
		if (cmd == "Heart") {
			this.receiveHeart(data);
			return;
		}
		data = JSON.parse(JSON.stringify(data)); //深拷贝
		console.log(
			"\n--服务器->客户端-----------------Message_STC-------------" +
			data.cmd +
			"----------------------\n",
			data,
			JSON.stringify(new Date()),
			"\n"
		);
		// //如果切后台  那么丢弃此包
		// if(cc.vv.GLDefine.isInBack){
		//     cc.log("giveup this data",JSON.stringify(data),JSON.stringify(new Date()))
		//     return ;
		// }

		if (data.is_ntc) {
			//分发到大厅网络中心  GameHallNetWork接收返回的消息
			if (cc.vv.NetGameHall && cc.vv.NetGameHall["receive" + cmd]) {
				console.log("______NetGameHall _ receive" + cmd);
				cc.vv.NetGameHall["receive" + cmd](data);
			}
			// 应服务器要求 这里特殊处理  LeaveTableNtc  有三种 大厅拦截统一处理 ，不抛到游戏中处理
			/**
			 * REASON_DELETE_TABLE = 3, --桌子被删除,玩家站起
			 * REASON_GAME_CLOSED = 6,    --游戏关闭
			 * REASON_GAME_RULECHANGE = 8,    --桌子配置更改
			 */
			console.log("cmd   is ***",cmd ,data);
			if (cmd == "LeavetableNtc" && (data.reason == glDefine.StandupReason.REASON_DELETE_TABLE|| data.reason == glDefine.StandupReason.REASON_GAME_CLOSED || data.reason == glDefine.StandupReason.REASON_GAME_RULECHANGE)) {
				let tipstr = "";
				if (data.reason == glDefine.StandupReason.REASON_DELETE_TABLE) {
					tipstr = "桌子被删除,玩家站起";
				}
				if (data.reason == glDefine.StandupReason.REASON_GAME_CLOSED) {
					tipstr = "游戏已经关闭";
				}
				if (data.reason == glDefine.StandupReason.REASON_GAME_RULECHANGE) {
					tipstr = "游戏桌子配置更改";
				}
				cc.vv.GLUtils.showAlert(tipstr, function () {
					cc.vv.sceneMgr.openScene("hall");
				}, null, null);
				return;
			}
			//通知到子游戏网络中心;
			cc.vv.eventCustom.emit("ServerNtc", data);
		} else if (cc.vv.baseDispatch && cc.vv.baseDispatch.isCallBackRegister(cmd)) {
			//todo: 统一的错误处理;
			if (data.errcodedes) {
				//	cc.log(data.errcode, data.errcodedes);
				if (data.errcodedes != "不在房间中" && data.errcodedes != "您的账号异常，请联系客服") {
					cc.vv.GLUtils.showTips(data.errcodedes);
				}
			}
			cc.vv.baseDispatch.dispacthMessage(cmd, data);
		}
	}
	pushMsg(preCmd, func) {
		this._sequenceMsg[preCmd] = func;
	}

	// update (dt) {

	// }
}
